﻿using System.IO;
using System.Linq;
using System.Xml.Linq;
using Palmmedia.ReportGenerator.Core.Logging;
using Palmmedia.ReportGenerator.Core.Properties;

namespace Palmmedia.ReportGenerator.Core.Parser.Preprocessing
{
    /// <summary>
    /// Preprocessor for Cobertura reports.
    /// </summary>
    internal class CoberturaReportPreprocessor
    {
        /// <summary>
        /// The Logger.
        /// </summary>
        private static readonly ILogger Logger = LoggerFactory.GetLogger(typeof(CoberturaReportPreprocessor));

        /// <summary>
        /// Executes the preprocessing of the report.
        /// </summary>
        /// <param name="report">The report.</param>
        internal void Execute(XContainer report)
        {
            var modules = report.Descendants("package")
                .ToArray();

            if (modules.Length == 0)
            {
                if (report.Descendants("packages").Elements("class").Any())
                {
                    Logger.Error(Resources.ErrorInvalidCoberturaReport);

                    // Fix malformed report files (See issues: #192, #209)
                    foreach (var packagesElement in report.Descendants("packages").ToArray())
                    {
                        packagesElement.Name = "classes";

                        var parent = packagesElement.Parent;

                        packagesElement.Remove();
                        parent.Add(new XElement("packages", new XElement("package", new XAttribute("name", "AutoGenerated"), packagesElement)));
                    }
                }
            }

            var sources = report.Descendants("sources")
                .Elements("source")
                .Select(s => s.Value)
                .Select(s => s.EndsWith(":") ? s + Path.DirectorySeparatorChar : s) // Issue: #115
                .ToArray();

            if (sources.Length == 0)
            {
                return;
            }

            var classes = report.Descendants("package")
                .Elements("classes")
                .Elements("class")
                .ToArray();

            if (sources.Length == 1)
            {
                foreach (var @class in classes)
                {
                    var fileNameAttribute = @class.Attribute("filename");

                    if (fileNameAttribute.Value.StartsWith("http://") || fileNameAttribute.Value.StartsWith("https://"))
                    {
                        continue;
                    }

                    string path = Path.Combine(sources[0], fileNameAttribute.Value)
                        .Replace('\\', Path.DirectorySeparatorChar)
                        .Replace('/', Path.DirectorySeparatorChar);
                    fileNameAttribute.Value = path;
                }
            }
            else
            {
                foreach (var @class in classes)
                {
                    var fileNameAttribute = @class.Attribute("filename");

                    if (fileNameAttribute.Value.StartsWith("http://") || fileNameAttribute.Value.StartsWith("https://"))
                    {
                        continue;
                    }

                    foreach (var source in sources)
                    {
                        string path = Path.Combine(source, fileNameAttribute.Value)
                            .Replace('\\', Path.DirectorySeparatorChar)
                            .Replace('/', Path.DirectorySeparatorChar);

                        if (File.Exists(path))
                        {
                            fileNameAttribute.Value = path;
                            break;
                        }
                    }
                }
            }
        }
    }
}
